package travelDream.ejb;

import java.util.ArrayList;
import java.util.List;

import javax.annotation.Resource;
import javax.ejb.EJBContext;
import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.NoResultException;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;

import travelDream.ejb.gestionePacchetto.GiornataDTO;
import travelDream.ejb.gestionePacchetto.PacchettoDTO;
import travelDream.ejb.gestionePacchetto.PacchettoInterface;
import travelDream.ejb.prodotto.base.EscursioneDTO;
import travelDream.ejb.prodotto.base.HotelDTO;
import travelDream.ejb.prodotto.base.TrasportoDTO;
import travelDream.ejb.prodotto.base.VoloDTO;
import travelDream.entities.Escursione;
import travelDream.entities.GiornatePredefinite;
import travelDream.entities.Hotel;
import travelDream.entities.PacchettoPredefinito;
import travelDream.entities.Trasporto;
import travelDream.entities.Volo;


@Stateless
public class GestionePacchettoPersistent implements PacchettoInterface{


	@PersistenceContext
	private EntityManager em;
	
    @Resource
    private EJBContext context;
	
	public void creaPacchettoPredefinito(PacchettoDTO pacchettoDTO){
		PacchettoPredefinito pack = new PacchettoPredefinito(pacchettoDTO);
		em.persist(pack);
		em.flush();
		pack = (PacchettoPredefinito) em.createQuery("SELECT p FROM PacchettoPredefinito p ORDER BY p.idPacchetto DESC").setMaxResults(1).getSingleResult();
		
		for(GiornataDTO gDTO : pacchettoDTO.getGiornate()){
			
			GiornatePredefinite giornata = new GiornatePredefinite(pack.getIdPacchetto(),gDTO.getNumeroGiornata(),null,null,null);
			em.persist(giornata);
			giornata = convertDTOtoE(gDTO);
			giornata.getGiornataPK().setIdPacchetto(pack.getIdPacchetto());
			
			//Dall'id del Volo estrae il trasporto!
			Integer idTrasporto = null;
			try{
				int idMezzo = gDTO.getTrasporto().getVolo().getId();
				Trasporto trasporto = em.createNamedQuery("Trasporto.findVoloByIdMezzo", Trasporto.class).setParameter("idMezzo", idMezzo).getSingleResult();
				idTrasporto = trasporto.getIdTrasporto();
			}
			catch(NoResultException | NullPointerException e){
			}
			giornata.setIdTrasporto(idTrasporto);
			updateGiornata(giornata);
			em.flush();
		}
		System.out.println("Pacchetto Creato");

		
	}
	
	private void updateGiornata(GiornatePredefinite g){
		Query query = em.createQuery("UPDATE GiornatePredefinite SET idEscursione = :idE, idHotel = :idH, idTrasporto = :idT "
				+ "WHERE giornataPK.idPacchetto = :idP AND giornataPK.giornata = :idG").
		setParameter("idP", g.getGiornataPK().getIdPacchetto()).
		setParameter("idG", g.getGiornataPK().getGiornata()).
		setParameter("idT", g.getIdTrasporto()).
		setParameter("idH", g.getIdHotel()).
		setParameter("idE", g.getIdEscursione());
		int result = query.executeUpdate();
	}
	
	public void modificaPacchetto(PacchettoDTO pacchettoDTO){
		em.merge(convertDTOtoE(pacchettoDTO));
		for(GiornataDTO gDTO: pacchettoDTO.getGiornate()){
			GiornatePredefinite giornata = new GiornatePredefinite(pacchettoDTO.getIdPacchetto(),gDTO.getNumeroGiornata(),null,null,null);
			try{
				em.createNamedQuery("GiornatePredefinite.exist", GiornatePredefinite.class).setParameter("idPacchetto", pacchettoDTO.getIdPacchetto()).setParameter("idGiornata", gDTO.getNumeroGiornata()).getSingleResult();
			}
			catch(NoResultException e){
				em.persist(giornata);
			}
			System.out.println("Modifico giornata");
			giornata = convertDTOtoE(gDTO);
			Integer idTrasporto = null;
			try{
				int idMezzo = gDTO.getTrasporto().getVolo().getId();
				Trasporto trasporto = em.createNamedQuery("Trasporto.findVoloByIdMezzo", Trasporto.class).setParameter("idMezzo", idMezzo).getSingleResult();
				idTrasporto = trasporto.getIdTrasporto();
			}
			catch(NoResultException | NullPointerException e){
			}
			giornata.setIdTrasporto(idTrasporto);
			updateGiornata(convertDTOtoE(gDTO));
		}
	}
	
	public void cancellaPacchettoById(int id){
		try{
			em.createQuery("DELETE FROM GiornatePredefinite WHERE giornataPK.idPacchetto = :idP").
			setParameter("idP", id).executeUpdate();
			em.createQuery("DELETE FROM PacchettoPredefinito WHERE idPacchetto = :idP").
			setParameter("idP", id).executeUpdate();
			em.flush();
		}
		catch(NoResultException e){
			System.out.println("Errore Delete");
		}
	}

	public List<PacchettoDTO> listaPacchettiPredefiniti(){
		List<PacchettoDTO> lista = new ArrayList<PacchettoDTO>();
		for(PacchettoPredefinito p : listaPacchettiPredefinitiPrivate()){
			lista.add(convertEtoDTO(p));
		}
		return lista;
	}
	
	private List<PacchettoPredefinito> listaPacchettiPredefinitiPrivate(){
		return em.createNamedQuery("PacchettoPredefinito.findAll", PacchettoPredefinito.class).getResultList();
	}
	
	private PacchettoPredefinito convertDTOtoE(PacchettoDTO pacchettoDTO){
		return new PacchettoPredefinito(pacchettoDTO);
	}
	
	public PacchettoDTO caricaPacchettoById(int idPacchetto){
		return convertEtoDTO(getPacchettoPredById(idPacchetto));
	}
	
	private PacchettoPredefinito getPacchettoPredById(int idPacchetto){
		return em.createNamedQuery("PacchettoPredefinito.findById", PacchettoPredefinito.class).setParameter("idPacchetto", idPacchetto).getSingleResult();
	}
	
	
	private PacchettoDTO convertEtoDTO(PacchettoPredefinito pacchetto){
		PacchettoDTO pack = new PacchettoDTO();
		pack.setIdPacchetto(pacchetto.getIdPacchetto());
		pack.setDescrizione(pacchetto.getDescrizione());
		pack.setNome(pacchetto.getNome());
		for(GiornataDTO gp : getGiornatePKDTO(pack.getIdPacchetto()))
			pack.addGiornata(gp);
		return pack;
	}
	
	private GiornataDTO convertEtoDTO(GiornatePredefinite giornata){
		 GiornataDTO giornataDTO = new GiornataDTO();
		 giornataDTO.setIdPacchetto(giornata.getGiornataPK().getIdPacchetto());
		 giornataDTO.setNumeroGiornata(giornata.getGiornataPK().getGiornata());
		 try{
				 giornataDTO.setEscursione(getEscursioneDTOById(giornata.getIdEscursione()));
		 }
		 catch(NullPointerException | NoResultException e){
			 giornataDTO.setEscursione(null);
		 }
		 try{
				 giornataDTO.setTrasporto(getTrasportoDTOByIdTrasporto(giornata.getIdTrasporto()));
		 }
		 catch(NullPointerException | NoResultException e){
			 giornataDTO.setTrasporto(null);
		 }
		 try{
				 giornataDTO.setHotel(getHotelDTOById(giornata.getIdHotel()));
		 }
		 catch(NullPointerException | NoResultException e){
			 giornataDTO.setHotel(null);
		 }
		 return giornataDTO;
	}
	
	private GiornatePredefinite convertDTOtoE(GiornataDTO giornataDTO){
		return new GiornatePredefinite(giornataDTO);	
	}
	
	private List<GiornataDTO> getGiornatePKDTO(int idPacchetto){
		List<GiornataDTO> giornateDTO = new ArrayList<GiornataDTO>();
		for(GiornatePredefinite gp : getGiornatePKPred(idPacchetto))
			giornateDTO.add(convertEtoDTO(gp));
		return giornateDTO;
	}
	
	private List<GiornatePredefinite> getGiornatePKPred(int idPacchetto){
		try{
		return em.createNamedQuery("GiornatePredefinite.findByPk", GiornatePredefinite.class).setParameter("idPacchetto", idPacchetto).getResultList();
		}
		catch(java.lang.NullPointerException | NoResultException e){
			System.out.println("Giornate non Trovate!");
		}
		return null;
	}

	
	/*
	 * -------------------------------------------------------------------------------------------- *
	 * -------------------------------------------------------------------------------------------- *
	 */
	
	public EscursioneDTO getEscursioneDTOById(int id) {
		return convertEtoDTO(getEscursioneById(id));
	}
	
	private Escursione getEscursioneById(int id){
		try{
			return em.createNamedQuery("Escursione.findById", Escursione.class).setParameter("id", id).getSingleResult();
		}
		catch(NoResultException | NullPointerException e){
			return null;
		}
	}
	
	private EscursioneDTO convertEtoDTO(Escursione e){
		EscursioneDTO esc = new EscursioneDTO(e.getIdEscursione(),e.getNome(),e.getDescrizione(), 
				e.getLuogo(), e.getCosto());
		return esc;
	}
	
	public HotelDTO getHotelDTOById(int id){
		return convertEtoDTO(getHotelById(id));
	}
	
	private Hotel getHotelById(int id){
		try{
			return em.createNamedQuery("Hotel.findById", Hotel.class).setParameter("id", id).getSingleResult();
		}
		catch(NoResultException | NullPointerException e){
			return null;
		}
	}
	
	private HotelDTO convertEtoDTO(Hotel h){
		HotelDTO hotel = new HotelDTO(h.getIdHotel(),h.getNome(),h.getDescrizione(), 
				h.getContatti(), h.getIndirizzo(), h.getStelle(), h.getCosto(), h.getLuogo());
		return hotel;
	}
	
	private Hotel convertDTOtoE(HotelDTO h){
		Hotel hotel = new Hotel(h);
		return hotel;
	}
	
	
	///////////////////////////////////////
	
	
	public VoloDTO getVoloDTOById(int id){
		return convertEtoDTO(getVoloById(id));
	}

	private Volo getVoloById(int id){
		try{
			return em.createNamedQuery("Volo.findById", Volo.class).setParameter("id", id).getSingleResult();
		}
		catch(NoResultException | NullPointerException e){
			return null;
		}
	}
	
	private Volo convertDTOtoE(VoloDTO voloDTO){
		return new Volo(voloDTO);
	}
	private VoloDTO convertEtoDTO(Volo volo){
		return new VoloDTO(volo.getIdVolo(), volo.getDescrizione(), volo.getLuogoPartenza(), 
				volo.getLuogoArrivo(), volo.getOrarioPartenza(), volo.getOrarioArrivo(), volo.getCosto());
	}
	
	////////////////////////////////////////////////////////////
	
	public TrasportoDTO getTrasportoDTOByIdTrasporto(int idTrasporto){
		return convertEtoDTO(getTrasportoByidTrasporto(idTrasporto));
	}
	
	private Trasporto getTrasportoByidTrasporto(int idTrasporto){
		try{
			return em.createNamedQuery("Trasporto.findByIdTrasporto", Trasporto.class).setParameter("idTrasporto", idTrasporto).getSingleResult();
		}
		catch(NoResultException | NullPointerException e){
			return null;
		}
	
	}
	
	public TrasportoDTO getTrasportoDTOByIdMezzo(int idMezzo){
		return convertEtoDTO(getTrasportoByIdMezzo(idMezzo));
	}
	
	public VoloDTO getVoloDTOByIdTrasporto(int idTrasporto){
		return convertEtoDTO(getVoloByIdTrasporto(idTrasporto));
	}
	
	public Volo getVoloByIdTrasporto(int idTrasporto){
		int idVolo = getTrasportoByidTrasporto(idTrasporto).getIdMezzo();
		return getVoloById(idVolo);
	}
	
	public Trasporto getTrasportoByIdMezzo(int idMezzo){
		try{
			return em.createNamedQuery("Trasporto.findVoloByIdMezzo", Trasporto.class).setParameter("idMezzo", idMezzo).getSingleResult();
		}
		catch(NoResultException | NullPointerException e){
			return null;
		}
	}
	
	private Trasporto convertDTOtoE(TrasportoDTO trasportoDTO){
		return new Trasporto(trasportoDTO.getIdTrasporto(), trasportoDTO.getIdMezzo(), trasportoDTO.getTipologia());
	}
	
	private TrasportoDTO convertEtoDTO(Trasporto trasporto){
		TrasportoDTO trasportoDTO = new TrasportoDTO(trasporto.getIdTrasporto(), trasporto.getIdMezzo(), trasporto.getTipologia());
		trasportoDTO.setVolo(getVoloDTOById(trasportoDTO.getIdMezzo()));
		return trasportoDTO;
	}
	
	
	
	
}
